package com.heima.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.article.entity.ApArticle;
import com.heima.article.entity.ApAuthor;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.ApArticleContentService;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.ApAuthorService;
import com.heima.article.service.FreemarkerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;
import com.heima.common.util.BeanHelper;
import com.heima.dto.ApUserFollow;
import com.heima.feign.ApArticleFeignClient;
import com.heima.feign.ApUserFeignClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.dtos.ArticleInfoDto;
import com.heima.model.article.dtos.UserBehaviorMsgDto;
import com.heima.model.media.dtos.WmNewsDownOrUpDTO;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.model.wemedia.dto.ArticleCommentManagementVO;
import com.heima.model.wemedia.dto.CommentManagementQueryDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.NativeWebRequest;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 文章信息表，存储已发布的文章 服务实现类
 * </p>
 *
 * @author HM
 * @since 2023-03-22
 */
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {
    @Autowired
    private ApUserFeignClient apUserFeignClient;
    @Autowired
    private ApArticleContentService contentService;
    @Autowired
    private ApAuthorService authorService;
    @Autowired
    @Lazy
    private FreemarkerService freemarkerService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public ArticleDto findById(Long id) {
        return this.baseMapper.findById(id);
    }


    /**
     * 这是一个feign接口，根据 wm_user_id, wm_news_id 删除文章
     */
    @Override
    public void delArticleByNewsId(Integer wmUserId, Integer wmNewsId) {
        ApAuthor authorDB = authorService.getByUserId(wmUserId);
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticle::getWmNewsId, wmNewsId);
        // 查询文章信息
        ApArticle articleDB = this.getOne(queryWrapper);
        // 判断作者信息是否一致
        if (!articleDB.getAuthorId().equals(authorDB.getId())) {
            throw new LeadException(AppHttpCodeEnum.UAER_NO_OPERATOR_AUTH);
        }
        // 判断是否下架
        if (!articleDB.getIsDown()) {
            throw new LeadException(AppHttpCodeEnum.WM_NEWS_STATUS_ERROR);
        }

        ApArticle upDateArticle = new ApArticle();
        upDateArticle.setId(articleDB.getId());
        upDateArticle.setIsDelete(true);
        this.updateById(upDateArticle);
    }

    @Override
    public UserBehaviorMsgDto loadArticleBehavior(ArticleInfoDto dto) {
        Integer userId = UserThreadLocalUtils.getUserId();
        //查询redis，获取用户行为
        UserBehaviorMsgDto userBehaviorMsgDto = (UserBehaviorMsgDto) redisTemplate.opsForHash().get("behavior:" + userId, dto.getArticleId());
        if (userBehaviorMsgDto == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //查询ap-user-follow表，判断用户是否关注作者
        ApUserFollow apUserFollow = apUserFeignClient.findByUserIdAndFollowId(userId, dto.getAuthorId());
        if (apUserFollow == null) {
            userBehaviorMsgDto.setIsfollow(false);
        } else {
            userBehaviorMsgDto.setIsfollow(true);
        }
        return userBehaviorMsgDto;
    }

    @Override
    public List<ApArticle> getLastestArticle(LocalDateTime localDateTime) {
        QueryWrapper<ApArticle> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ApArticle::getIsDown, false);
        queryWrapper.lambda().eq(ApArticle::getIsDelete, false);
        queryWrapper.lambda().ge(ApArticle::getPublishTime, localDateTime);
        List<ApArticle> list = this.list(queryWrapper);
        return list;

    }

    @Override
    public List<ArticleCommentManagementVO> findNewsComments(CommentManagementQueryDTO dto) {
        //获取自媒体作者id
        ApAuthor author = authorService.getByUserId(dto.getWmUserId());

        //分页查询条件
        QueryWrapper<ApArticle> queryWrapper = new QueryWrapper<>();
        //自媒体作者id
        queryWrapper.lambda().eq(ApArticle::getAuthorId, author.getId());
        //时间条件
        queryWrapper.lambda().ge(ApArticle::getPublishTime, dto.getBeginDate());
        queryWrapper.lambda().le(ApArticle::getPublishTime, dto.getEndDate());
        //排序
        queryWrapper.lambda().orderByDesc(ApArticle::getPublishTime);
        //分页条件
        Page<ApArticle> ipage = new Page<>(dto.getPage(), dto.getSize());
        Page<ApArticle> page = this.page(ipage, queryWrapper);
        //遍历，组装数据
        List<ArticleCommentManagementVO> articleCommentManagementVOList = new ArrayList<>();
        for (ApArticle apArticle : page.getRecords()) {
            ArticleCommentManagementVO articleCommentManagementVO = BeanHelper.copyProperties(apArticle, ArticleCommentManagementVO.class);
            articleCommentManagementVOList.add(articleCommentManagementVO);
        }
        return articleCommentManagementVOList;
    }

    @Override
    public Integer findWmNewsIdByArticleId(Long id) {
        ApArticle apArticle = this.getById(id);
        return apArticle.getWmNewsId();
    }

    @Override
    public void updateArticleEnableComment(ArticleDto articleDto) {
        ApArticle apArticle=new ApArticle();
        apArticle.setId(articleDto.getId());
        apArticle.setIsComment(articleDto.getIsComment());
        this.updateById(apArticle);
    }

    @Override
    public List<ArticleDto> findByPage(int pageNum, int pageSize) {
        Page<ApArticle> ipage = new Page<>(pageNum, pageSize);
        return this.baseMapper.findByPage(ipage);
    }

    @Override
    public void downOrUp(WmNewsDownOrUpDTO dto) {
        // 根据自媒体文章的id更新article
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticle::getWmNewsId, dto.getId());
        ApArticle updateArticle = new ApArticle();
        updateArticle.setIsDown(!dto.getEnable());
        this.update(updateArticle, queryWrapper);
    }

    @Override
    public List<ApArticle> load(ArticleHomeDto dto) {
        return loadmore(dto);
    }

    @Override
    public List<ApArticle> loadmore(ArticleHomeDto dto) {
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        // 查询
        queryWrapper.eq(ApArticle::getIsDown, false);
        queryWrapper.eq(ApArticle::getIsDelete, false);
        queryWrapper.eq(dto.getChannelId() != null && dto.getChannelId() > 0, ApArticle::getChannelId, dto.getChannelId());
        queryWrapper.lt(dto.getMinTime() != null, ApArticle::getPublishTime, dto.getMinTime());
        // 排序
        queryWrapper.orderByDesc(ApArticle::getPublishTime);
        // 分页
        Page<ApArticle> ipage = new Page<>(1, dto.getSize());
        Page<ApArticle> page = this.page(ipage, queryWrapper);

        return page.getRecords();
    }

    @Override
    public List<ApArticle> loadnew(ArticleHomeDto dto) {
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        // 查询
        queryWrapper.eq(ApArticle::getIsDown, false);
        queryWrapper.eq(ApArticle::getIsDelete, false);
        queryWrapper.eq(dto.getChannelId() != null && dto.getChannelId() > 0, ApArticle::getChannelId, dto.getChannelId());
        queryWrapper.gt(dto.getMaxTime() != null, ApArticle::getPublishTime, dto.getMaxTime());
        // 排序
        queryWrapper.orderByDesc(ApArticle::getPublishTime);
        // 分页
        Page<ApArticle> ipage = new Page<>(1, dto.getSize());
        Page<ApArticle> page = this.page(ipage, queryWrapper);
        return page.getRecords();
    }


    @Override
    // @GloablTransactional
    public Long createArticle(WmNewsResultDTO dto) {
        Long articleId = null;
        // 先查询是否存在article。没有则插入，有则更新
        // ap_article
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticle::getWmNewsId, dto.getId());
        ApArticle articleDB = this.getOne(queryWrapper);
        if (articleDB == null) {
            // insert
            ApArticle insertArticle = BeanHelper.copyProperties(dto, ApArticle.class);
            insertArticle.setId(null);//FIXME
            insertArticle.setLayout(dto.getType());
            insertArticle.setCreatedTime(new Date());
            insertArticle.setAuthorId(0);//TODO 自己补充
            insertArticle.setAuthorName("test");//TODO
            insertArticle.setFlag(0);//TODO
            insertArticle.setLikes(0L);
            insertArticle.setCollection(0L);
            insertArticle.setViews(0L);
            insertArticle.setComments(0L);
            insertArticle.setIsComment(true);
            insertArticle.setIsForward(true);
            insertArticle.setIsDown(false);
            insertArticle.setIsDelete(false);
            insertArticle.setWmNewsId(dto.getId());
            this.save(insertArticle);
            articleId = insertArticle.getId();
        } else {
            // update
            ApArticle updateArticle = BeanHelper.copyProperties(dto, ApArticle.class);
            updateArticle.setId(articleDB.getId());
            updateArticle.setLayout(dto.getType());
            updateArticle.setAuthorId(0);//TODO 自己补充
            updateArticle.setAuthorName("test");//TODO
            updateArticle.setWmNewsId(dto.getId());
            this.updateById(updateArticle);
            articleId = articleDB.getId();
        }
        // ap_article_content
        contentService.createArticleContent(articleId, dto);
        // 生成详情，并上传到minio，更新ap_artile中的static_url
        freemarkerService.asyncCreateHtmlAndUploadMinio(articleId, dto);
        return articleId;
    }
}
